/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * Project Name: lmrp-android app
 * Create Time: 16-2-16 下午6:44
 */

package com.lenovo.mso2o.ui.fragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.LongSparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiBoundSearchOption;
import com.baidu.mapapi.search.poi.PoiCitySearchOption;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.platform.comjni.map.basemap.BaseMapCallback;
import com.baidu.platform.comjni.map.basemap.b;
import com.lenovo.framework.base.FBaseActivity;
import com.lenovo.framework.base.InjectableDialogFragment;
import com.lenovo.framework.base.InjectableFragmentActivity;
import com.lenovo.framework.conf.FConstants;
import com.lenovo.framework.util.DLog;
import com.lenovo.framework.util.ReflectHelper;
import com.lenovo.mso2o.MSApplication;
import com.lenovo.mso2o.R;
import com.lenovo.mso2o.conf.MSConstants;
import com.lenovo.mso2o.entity.g.SiteDao;
import com.lenovo.mso2o.entity.g.UploadLocation;
import com.lenovo.mso2o.entity.g.UploadLocationDao;
import com.lenovo.mso2o.ui.adapter.PoiAdapter;
import com.lenovo.mso2o.util.CommonUtil;
import com.lenovo.mso2o.util.PrefExtraUtils;
import com.lenovo.mso2o.util.Utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import butterknife.Bind;
import butterknife.OnClick;
import rx.Subscription;

/**
 * Created by hippo on 11/14/15.
 */
public class POISearchDialogFragment extends InjectableDialogFragment implements TextWatcher, PoiAdapter.OnRecyclerViewItemClickListener, BDLocationListener {

    @Bind(R.id.recycler_map_search)
    RecyclerView mRecyclerView;
    @Bind(R.id.edt_tool_search)
    EditText edtToolSearch;
    @Bind(R.id.img_tool_mic)
    TextView imgToolMic;
    @Bind(R.id.iv_for_del_place_text)
    ProgressBar mProgress;
    private String mKeyword;
    public static final String RESULT_KEY = "name";
    public static final String TAG = "search_toolbar_dialog";
    public static final String TYPE_KEY = "type_key";
    public static final String RESULT_VALUE = "id";
    // 定位相关
    private LocationClient mLocClient;
    private SiteDao siteDao;
    private PoiSearch mPoiSearch = null;
    private LatLng latLng;
    private Subscription _subscription;
    private GeoCoder geoCoder;
    //private CompositeSubscription eventSubscription;
    //private ServiceConnection serviceConnection;
    private UploadLocationDao locationDao;
    private String city;

    @OnClick(R.id.img_tool_back)
    public void clickToolBack() {
        dismiss();
    }

    @OnClick(R.id.img_tool_mic)
    public void clicksearch() {
        Intent intent = new Intent(getActivity(), InjectableFragmentActivity.class);
        intent.putExtra(InjectableFragmentActivity.FRAGMENT_CLASS_NAME, POISearchResultFragment.class.getName());
        intent.putExtra(FConstants.NAME_SEARCH_PLACE, edtToolSearch.getText().toString().trim());
        POISearchResultFragment.callBackObj = mInterface;
        startActivity(intent);
        dismiss();
    }

    /*@OnClick(R.id.iv_for_del_place_text)
    public void clickDelText(){
        edtToolSearch.setText("");
        imgToolMic.setVisibility(View.GONE);
    }*/

    /*public void subscribeSearch() {
        if (_subscription == null || _subscription.isUnsubscribed())
            _subscription =
                    RxTextView.afterTextChangeEvents(edtToolSearch)
                            .compose(this.<TextViewAfterTextChangeEvent>bindToLifecycle())
                            .observeOn(Schedulers.computation())
                            .debounce(BaseActionBarMockingActivity.QUERY_UPDATE_DELAY_MILLIS, TimeUnit.MILLISECONDS)
                            .observeOn(AndroidSchedulers.mainThread())
                            .filter(new Func1<TextViewAfterTextChangeEvent, Boolean>() {
                                @Override
                                public Boolean call(TextViewAfterTextChangeEvent textViewTextChangeEvent) {
                                    //DLog.w("search", textViewTextChangeEvent.editable().toString());
                                    if (textViewTextChangeEvent.editable().length() > 0) {
                                        */

    /**
     * 得到光标开始和结束位置 ,超过最大数后记录刚超出的数字索引进行控制
     *//*
                                        //显示搜索按钮
                                        imgToolMic.setVisibility(View.VISIBLE);
                                        //ivDelText.setVisibility(View.VISIBLE);
                                    } else {
                                        //显示搜索按钮
                                        imgToolMic.setVisibility(View.GONE);
                                        //ivDelText.setVisibility(View.GONE);
                                    }
                                    if (textViewTextChangeEvent.editable().toString().trim().length() == 0)
                                        return false;
                                    else
                                        return true;
                                }
                            })
                            .observeOn(Schedulers.computation())
                            .flatMap(new Func1<TextViewAfterTextChangeEvent, Observable<PoiResult>>() {
                                @Override
                                public Observable<PoiResult> call(TextViewAfterTextChangeEvent textViewTextChangeEvent) {
                                    final String keyword = textViewTextChangeEvent.editable().toString();
                                    Observable o = Observable.create(new Observable.OnSubscribe<PoiResult>() {
                                        @Override
                                        public void call(final Subscriber<? super PoiResult> subscriber) {
                                            mPoiSearch.setOnGetPoiSearchResultListener(null);
                                            mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {
                                                @Override
                                                public void onGetPoiResult(PoiResult poiResult) {
                                                    subscriber.onNext(poiResult);
                                                }

                                                @Override
                                                public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
                                                }
                                            });
                                            DLog.w("search", "triggered");
                                            //获取的经纬度不为空：若有城市信息, 则直接搜索，若无城市信息，则根据经纬度反解码出城市信息，再搜索
                                            //经纬度为空：区域内检索
                                            if (latLng != null) {
                                                //mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword(keyword).radius(Integer.MAX_VALUE).location(latLng).pageCapacity(20).sortType(PoiSortType.comprehensive));
                                                mPoiSearch.searchInCity((new PoiCitySearchOption())
                                                        .city(city)
                                                        .keyword(keyword)
                                                        .pageCapacity(20)
                                                        .pageNum(0));

                                            } else {
                                                CoordinateConverter converter = new CoordinateConverter();
                                                converter.from(CoordinateConverter.CoordType.GPS);
                                                // sourceLatLng待转换坐标
                                                //东北 50.80388021930629|130.89661430611355
                                                //西南 20.152722420924178|83.68217077464115
                                                LatLng southwest = new LatLng(20.152722420924178, 83.68217077464115);// 西南
                                                LatLng northeast = new LatLng(50.80388021930629, 130.89661430611355);// 东北

                                                LatLngBounds latLngBounds = new LatLngBounds.Builder()
                                            *//*.include(converter.coord(new LatLng(53.3472020000, 136.8129920000)).convert())
                                            .include(converter.coord(new LatLng(3.1449770000, 74.2466830000)).convert())*//*
                                                        .include(converter.coord(southwest).convert())
                                                        .include(converter.coord(northeast).convert())
                                                        .build();
                                                mProgress.setVisibility(View.VISIBLE);
                                                mPoiSearch.searchInBound(new PoiBoundSearchOption().bound(latLngBounds).keyword(keyword).pageCapacity(20).pageNum(0));
                                            }
                                        }
                                    });
                                    return o;
                                }
                            })
                            .observeOn(AndroidSchedulers.mainThread())
                            .map(new Func1<PoiResult, Object>() {
                                @Override
                                public Object call(PoiResult poiResult) {
                                    onGetPoiResult(poiResult);
                                    return poiResult;
                                }
                            })
                            .unsubscribeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Subscriber<Object>() {
                                @Override
                                public void onCompleted() {

                                }

                                @Override
                                public void onError(Throwable e) {

                                }

                                @Override
                                public void onNext(Object o) {

                                }
                            });
    }*/
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NORMAL, R.style.MaterialSearch);
        //第一步，创建POI检索实例
        //初始化搜索模块，注册搜索事件监听
        mPoiSearch = PoiSearch.newInstance();
        locationDao = MSApplication.getDaoSession().getUploadLocationDao();
        //mSuggestionSearch = SuggestionSearch.newInstance();
        //mSuggestionSearch.setOnGetSuggestionResultListener(this);
    }

    @Override
    public void onResume() {
        // Auto size the dialog based on it's contents
        getDialog().getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        getDialog().getWindow().setGravity(Gravity.TOP);
        getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        edtToolSearch.addTextChangedListener(this);
        String editString = edtToolSearch.getText().toString();
        if (editString.length() <= 0) {
            imgToolMic.setVisibility(View.GONE);
            //ivDelText.setVisibility(View.GONE);
        }
        super.onResume();

        if (!CommonUtil.isGPSEnable(getActivity())) {
            Toast.makeText(getActivity(), "无法定位,请开启或重启gps", Toast.LENGTH_SHORT).show();
            return;
        }
        //subscribeSearch();
        // 定位初始化
        mLocClient = new LocationClient(getActivity());
        mLocClient.registerLocationListener(this);
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true); // 打开gps
        option.setCoorType("bd09ll"); // 设置坐标类型
        option.setScanSpan(1000);
        mLocClient.setLocOption(option);
        mLocClient.start();
        ((FBaseActivity) getActivity()).processPreview("定位中", null, false);
        String savedKeyword = PrefExtraUtils.getString(getString(R.string.key_word_address), "");
        edtToolSearch.setText(savedKeyword);
        edtToolSearch.setSelection(edtToolSearch.getText().length());
        PrefExtraUtils.put(getString(R.string.key_word_address), "");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        //Intent intent = new Intent(getContext().getApplicationContext(), LocationService.class);
        //serviceConnection = LocationService.connection(this, intent);
        //getActivity().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        PoiAdapter poiAdapter = new PoiAdapter(null);
        poiAdapter.setLatLng(latLng);
        poiAdapter.setOnItemClickListener(this);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.setAdapter(poiAdapter);
        return view;
    }

    @Override
    public int provideContentRes() {
        return R.layout.view_toolbar_search;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Bundle b = getArguments();
        String key = b.getString(TYPE_KEY);
        loadToolBarSearch(getContext(), view, key);
        mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {
            @Override
            public void onGetPoiResult(PoiResult poiResult) {
                onGetPoisResult(poiResult);
            }

            @Override
            public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
            }
        });
    }

    protected void loadToolBarSearch(final Context context, View view, final String key) {
        edtToolSearch.setHint("请输入关键字");
        setCancelable(true);
        if (edtToolSearch.length() == 0)
            edtToolSearch.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    edtToolSearch.setText("");
                }
            });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mPoiSearch != null) {
            mPoiSearch.setOnGetPoiSearchResultListener(null);
            mPoiSearch.destroy();
        }
        if (_subscription != null)
            _subscription.unsubscribe();

        if (siteDao != null) {
            siteDao = null;
        }
        // 释放地理编码检索实例
        if (geoCoder != null) {
            geoCoder.destroy();
        }
        //eventSubscription.unsubscribe();
    }

    public void onPause() {
        PrefExtraUtils.put(getString(R.string.key_word_address), mKeyword);
        super.onPause();
        LongSparseArray<b> sparseArray =
                ReflectHelper.getFieldValue(new BaseMapCallback(), "a");
        DLog.i("sparsearray", "" + sparseArray);
        if (sparseArray != null) {
            Method gc = ReflectHelper.getMethod(LongSparseArray.class, "gc");
            DLog.i("gc", "" + gc);
            try {
                DLog.i("fix callback", "clearing");
                gc.invoke(sparseArray);
            } catch (IllegalAccessException e) {
                DLog.p(e);
            } catch (InvocationTargetException e) {
                DLog.p(e);
            }
        }
    }

    @Override
    protected void onFragmentInVisible(Bundle savedInstanceState) {

    }

    @Override
    protected void onFragmentVisible(Bundle savedInstanceState) {

    }

    public void onGetPoisResult(PoiResult poiResult) {
        mProgress.setVisibility(View.GONE);
        if (poiResult == null) {
            //Toast.makeText(POISearchDialogFragment.this.getActivity(), "搜索失败，请用其他关键字搜搜", Toast.LENGTH_SHORT).show();
            return;
        }
        final List<PoiInfo> poiInfos = poiResult.getAllPoi();
        if (poiInfos == null || poiInfos.size() <= 0) {
            //Toast.makeText(POISearchDialogFragment.this.getActivity(), "搜索失败，请用其他关键字搜搜", Toast.LENGTH_SHORT).show();
            return;
        }
        if (poiInfos != null && poiInfos.size() > 0) {
            imgToolMic.setVisibility(View.VISIBLE);
            ((PoiAdapter) mRecyclerView.getAdapter()).setList(poiInfos);
            for (PoiInfo info : poiInfos) {
                DLog.w("search:", info.name);
            }
        }
    }

    @Override
    public void onItemClick(int position, String address, LatLng loc) {
        if (loc == null) {
            Toast.makeText(getActivity(), "无法获取经纬度", Toast.LENGTH_SHORT).show();
            return;
        }
        Bundle bundle = new Bundle();
        bundle.putString("address", address);
        bundle.putDouble("latitude", loc.latitude);
        bundle.putDouble("longtitude", loc.longitude);
        mInterface.onRetrieveDialogFragmentData(bundle, MSConstants.FragmentType.DIALOG_SEARCH_FRAGMENT_MS);
        List<UploadLocation> existList = locationDao.queryBuilder().where(UploadLocationDao.Properties.Location.eq(address)).list();
        if (existList == null || existList.size() <= 0) {
            UploadLocation location = new UploadLocation();
            location.setLocation(address);
            location.setLatitude(loc.latitude);
            location.setLongtitude(loc.longitude);
            locationDao.insert(location);
        }
        InputMethodManager imm = (InputMethodManager) (getActivity().getSystemService(Context.INPUT_METHOD_SERVICE));
        imm.hideSoftInputFromWindow(edtToolSearch.getWindowToken(), 0); //强制隐藏键盘
        dismiss();
    }

    @Override
    public void onReceiveLocation(BDLocation location) {
        ((FBaseActivity) getActivity()).processDismiss();
        if (location != null) {
            mLocClient.stop();
            this.latLng = new LatLng(location.getLatitude(), location.getLongitude());
            /*if(serviceConnection != null) {
                try {
                    getActivity().unbindService(serviceConnection);
                    serviceConnection = null;
                }catch (Exception e){
                    serviceConnection = null;
                    DLog.p(e);
                }
            }*/
            city = location.getCity();
            if (city != null && city.contains("市")) {
                city = city.substring(0, city.length() - 1);
            }
            // 创建地理编码检索实例
            geoCoder = GeoCoder.newInstance();
            OnGetGeoCoderResultListener listener = new OnGetGeoCoderResultListener() {
                // 反地理编码查询结果回调函数
                @Override
                public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
                    if (result != null) {
                        city = result.getAddressDetail().city;
                    }
                    if (city == null) {
                        city = "上海";
                    } else if (city.contains("市")) {
                        city = city.substring(0, city.length() - 1);
                    }

                }

                // 地理编码查询结果回调函数
                @Override
                public void onGetGeoCodeResult(GeoCodeResult result) {
                    if (result == null
                            || result.error != SearchResult.ERRORNO.NO_ERROR) {
                        // 没有检测到结果
                    }
                }
            };
            // 设置地理编码检索监听者
            geoCoder.setOnGetGeoCodeResultListener(listener);
            geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));
        } else {
            city = "上海";
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {

        //mPoiSearch.setOnGetPoiSearchResultListener(null);

        //获取的经纬度不为空：若有城市信息, 则直接搜索，若无城市信息，则根据经纬度反解码出城市信息，再搜索
        //经纬度为空：区域内检索
        mKeyword = s.toString();
        if (mKeyword == null || mKeyword.length() <= 0) {
            return;
        }
        if (latLng != null) {
            //mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword(keyword).radius(Integer.MAX_VALUE).location(latLng).pageCapacity(20).sortType(PoiSortType.comprehensive));
            mPoiSearch.searchInCity((new PoiCitySearchOption())
                    .city(city == null ? "上海" : city)
                    .keyword(mKeyword == null ? " " : mKeyword)
                    .pageCapacity(20)
                    .pageNum(0));

        } else {
            CoordinateConverter converter = new CoordinateConverter();
            converter.from(CoordinateConverter.CoordType.GPS);
            // sourceLatLng待转换坐标
            //东北 50.80388021930629|130.89661430611355
            //西南 20.152722420924178|83.68217077464115
            LatLng southwest = new LatLng(20.152722420924178, 83.68217077464115);// 西南
            LatLng northeast = new LatLng(50.80388021930629, 130.89661430611355);// 东北

            LatLngBounds latLngBounds = new LatLngBounds.Builder()
                    .include(converter.coord(southwest).convert())
                    .include(converter.coord(northeast).convert())
                    .build();
            mProgress.setVisibility(View.VISIBLE);
            mPoiSearch.searchInBound(new PoiBoundSearchOption().bound(latLngBounds).keyword(mKeyword).pageCapacity(20).pageNum(0));
        }
    }
}
